In [1]:
#01 Import, install and create path
In [2]:
#01.1 Install 3D visualizer
!pip install plotly==5.12.0
Requirement already satisfied: plotly==5.12.0 in c:\users\jonba\anaconda3\lib\site-packages (5.12.0) Requirement already satisfied: tenacity>=6.2.0 in c:\users\jonba\anaconda3\lib\site-packages (from plotly==5.12.0) (8.2.2)
In [3]:
#01.2 Import libraries
import pandas as pd
import plotly.express as px
import numpy as np
import matplotlib.pyplot as plt
import os
from mpl_toolkits import mplot3d
from plotly.offline import download_plotlyjs, init_notebook_mode
from plotly.offline import plot, iplot
import plotly.graph_objects as go
In [4]:
#01.3 Create a path to where your data is stored
path = r'D:\Joan\CareerFoundry\Machine Learning\Datasets\Raw Data'
In [5]:
#01.4 Read in the European weather data
climate = pd.read_csv(os.path.join(path, 'Dataset-weather-prediction-dataset-processed.csv'))
climate
Out[5]:
| DATE | MONTH | BASEL_cloud_cover | BASEL_wind_speed | BASEL_humidity | BASEL_pressure | BASEL_global_radiation | BASEL_precipitation | BASEL_snow_depth | BASEL_sunshine | ... | VALENTIA_cloud_cover | VALENTIA_humidity | VALENTIA_pressure | VALENTIA_global_radiation | VALENTIA_precipitation | VALENTIA_snow_depth | VALENTIA_sunshine | VALENTIA_temp_mean | VALENTIA_temp_min | VALENTIA_temp_max | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 19600101 | 1 | 7 | 2.1 | 0.85 | 1.0180 | 0.32 | 0.09 | 0 | 0.7 | ... | 5 | 0.88 | 1.0003 | 0.45 | 0.34 | 0 | 4.7 | 8.5 | 6.0 | 10.9 |
| 1 | 19600102 | 1 | 6 | 2.1 | 0.84 | 1.0180 | 0.36 | 1.05 | 0 | 1.1 | ... | 7 | 0.91 | 1.0007 | 0.25 | 0.84 | 0 | 0.7 | 8.9 | 5.6 | 12.1 |
| 2 | 19600103 | 1 | 8 | 2.1 | 0.90 | 1.0180 | 0.18 | 0.30 | 0 | 0.0 | ... | 7 | 0.91 | 1.0096 | 0.17 | 0.08 | 0 | 0.1 | 10.5 | 8.1 | 12.9 |
| 3 | 19600104 | 1 | 3 | 2.1 | 0.92 | 1.0180 | 0.58 | 0.00 | 0 | 4.1 | ... | 7 | 0.86 | 1.0184 | 0.13 | 0.98 | 0 | 0.0 | 7.4 | 7.3 | 10.6 |
| 4 | 19600105 | 1 | 6 | 2.1 | 0.95 | 1.0180 | 0.65 | 0.14 | 0 | 5.4 | ... | 3 | 0.80 | 1.0328 | 0.46 | 0.00 | 0 | 5.7 | 5.7 | 3.0 | 8.4 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 22945 | 20221027 | 10 | 1 | 2.1 | 0.79 | 1.0248 | 1.34 | 0.22 | 0 | 7.7 | ... | 5 | 0.82 | 1.0142 | 1.13 | 0.41 | 0 | 3.4 | 10.7 | 7.9 | 13.5 |
| 22946 | 20221028 | 10 | 6 | 2.1 | 0.77 | 1.0244 | 1.34 | 0.22 | 0 | 5.4 | ... | 5 | 0.82 | 1.0142 | 1.13 | 0.41 | 0 | 3.4 | 10.7 | 7.9 | 13.5 |
| 22947 | 20221029 | 10 | 4 | 2.1 | 0.76 | 1.0227 | 1.34 | 0.22 | 0 | 6.1 | ... | 5 | 0.82 | 1.0142 | 1.13 | 0.41 | 0 | 3.4 | 10.7 | 7.9 | 13.5 |
| 22948 | 20221030 | 10 | 5 | 2.1 | 0.80 | 1.0212 | 1.34 | 0.22 | 0 | 5.8 | ... | 5 | 0.82 | 1.0142 | 1.13 | 0.41 | 0 | 3.4 | 10.7 | 7.9 | 13.5 |
| 22949 | 20221031 | 10 | 5 | 2.1 | 0.84 | 1.0193 | 1.34 | 0.22 | 0 | 3.2 | ... | 5 | 0.82 | 1.0142 | 1.13 | 0.41 | 0 | 3.4 | 10.7 | 7.9 | 13.5 |
22950 rows × 170 columns
In [6]:
#02 Adjust df and create subsets
In [7]:
#02.1 Reduce to just the mean temperatures
df = climate[['DATE', 'MONTH','BASEL_temp_mean',
'BELGRADE_temp_mean',
'BUDAPEST_temp_mean',
'DEBILT_temp_mean',
'DUSSELDORF_temp_mean',
'GDANSK_temp_mean',
'HEATHROW_temp_mean',
'KASSEL_temp_mean',
'LJUBLJANA_temp_mean',
'MAASTRICHT_temp_mean',
'MADRID_temp_mean',
'MUNCHENB_temp_mean',
'OSLO_temp_mean',
'ROMA_temp_mean',
'SONNBLICK_temp_mean',
'STOCKHOLM_temp_mean',
'TOURS_temp_mean',
'VALENTIA_temp_mean']].copy()
In [8]:
#02.2 show dataframe
df
Out[8]:
| DATE | MONTH | BASEL_temp_mean | BELGRADE_temp_mean | BUDAPEST_temp_mean | DEBILT_temp_mean | DUSSELDORF_temp_mean | GDANSK_temp_mean | HEATHROW_temp_mean | KASSEL_temp_mean | LJUBLJANA_temp_mean | MAASTRICHT_temp_mean | MADRID_temp_mean | MUNCHENB_temp_mean | OSLO_temp_mean | ROMA_temp_mean | SONNBLICK_temp_mean | STOCKHOLM_temp_mean | TOURS_temp_mean | VALENTIA_temp_mean | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 19600101 | 1 | 6.5 | 3.7 | 2.4 | 9.3 | 10.0 | 0.8 | 10.6 | 7.9 | -0.6 | 9.5 | 7.6 | 6.9 | 4.9 | 7.8 | -5.9 | 4.2 | 10.0 | 8.5 |
| 1 | 19600102 | 1 | 6.1 | 2.9 | 2.3 | 7.7 | 8.2 | 1.6 | 6.1 | 7.7 | 2.1 | 8.6 | 9.8 | 6.2 | 3.4 | 12.2 | -9.5 | 4.0 | 9.5 | 8.9 |
| 2 | 19600103 | 1 | 8.5 | 3.1 | 2.7 | 6.8 | 7.1 | 0.7 | 8.4 | 6.5 | 4.6 | 6.9 | 8.6 | 5.8 | 1.9 | 10.2 | -9.5 | 2.4 | 10.3 | 10.5 |
| 3 | 19600104 | 1 | 6.3 | 2.0 | 2.0 | 6.7 | 6.8 | -0.1 | 9.4 | 5.8 | 3.2 | 7.0 | 10.3 | 3.9 | 3.0 | 10.8 | -11.5 | 1.2 | 11.2 | 7.4 |
| 4 | 19600105 | 1 | 3.0 | 2.0 | 2.5 | 8.0 | 7.7 | 0.4 | 8.9 | 5.4 | 3.6 | 8.1 | 12.1 | 1.8 | 3.7 | 9.9 | -9.3 | 3.3 | 11.4 | 5.7 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 22945 | 20221027 | 10 | 15.9 | 18.2 | 11.7 | 15.7 | 17.8 | 11.5 | 16.4 | 9.1 | 14.7 | 18.6 | 20.0 | 14.3 | 9.7 | 15.4 | 0.6 | 11.5 | 19.9 | 10.7 |
| 22946 | 20221028 | 10 | 16.7 | 15.9 | 11.7 | 16.0 | 19.4 | 11.7 | 15.8 | 9.1 | 12.9 | 18.9 | 19.1 | 16.1 | 10.9 | 15.4 | 2.3 | 12.5 | 20.3 | 10.7 |
| 22947 | 20221029 | 10 | 16.7 | 13.4 | 11.7 | 15.8 | 18.2 | 14.2 | 16.5 | 9.1 | 13.2 | 18.2 | 19.0 | 17.4 | 9.7 | 15.4 | 3.3 | 13.1 | 20.6 | 10.7 |
| 22948 | 20221030 | 10 | 15.4 | 15.0 | 11.7 | 14.4 | 16.7 | 11.0 | 15.2 | 9.1 | 14.0 | 16.3 | 15.7 | 14.5 | 5.9 | 15.4 | 3.4 | 7.5 | 15.9 | 10.7 |
| 22949 | 20221031 | 10 | 13.5 | 14.4 | 11.7 | 12.8 | 15.2 | 9.3 | 13.7 | 9.1 | 13.6 | 15.3 | 14.1 | 12.9 | 9.2 | 15.4 | 1.7 | 9.7 | 16.8 | 10.7 |
22950 rows × 20 columns
In [9]:
#02.3 Drop DATE and MONTH columns
notemp = df.drop(['DATE','MONTH'], axis=1)
In [10]:
#02.4 create whisker plot to see variations in temperature
notemp.boxplot(figsize=(15,15))
plt.xticks(rotation=90)
Out[10]:
(array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18]),
[Text(1, 0, 'BASEL_temp_mean'),
Text(2, 0, 'BELGRADE_temp_mean'),
Text(3, 0, 'BUDAPEST_temp_mean'),
Text(4, 0, 'DEBILT_temp_mean'),
Text(5, 0, 'DUSSELDORF_temp_mean'),
Text(6, 0, 'GDANSK_temp_mean'),
Text(7, 0, 'HEATHROW_temp_mean'),
Text(8, 0, 'KASSEL_temp_mean'),
Text(9, 0, 'LJUBLJANA_temp_mean'),
Text(10, 0, 'MAASTRICHT_temp_mean'),
Text(11, 0, 'MADRID_temp_mean'),
Text(12, 0, 'MUNCHENB_temp_mean'),
Text(13, 0, 'OSLO_temp_mean'),
Text(14, 0, 'ROMA_temp_mean'),
Text(15, 0, 'SONNBLICK_temp_mean'),
Text(16, 0, 'STOCKHOLM_temp_mean'),
Text(17, 0, 'TOURS_temp_mean'),
Text(18, 0, 'VALENTIA_temp_mean')])
In [11]:
#02.5 Reduce to single year
dfyear = df[df['DATE'].astype(str).str.contains('2000')]
dfyear
Out[11]:
| DATE | MONTH | BASEL_temp_mean | BELGRADE_temp_mean | BUDAPEST_temp_mean | DEBILT_temp_mean | DUSSELDORF_temp_mean | GDANSK_temp_mean | HEATHROW_temp_mean | KASSEL_temp_mean | LJUBLJANA_temp_mean | MAASTRICHT_temp_mean | MADRID_temp_mean | MUNCHENB_temp_mean | OSLO_temp_mean | ROMA_temp_mean | SONNBLICK_temp_mean | STOCKHOLM_temp_mean | TOURS_temp_mean | VALENTIA_temp_mean | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 14610 | 20000101 | 1 | 2.9 | -2.5 | -4.9 | 6.1 | 4.2 | -0.7 | 7.0 | 3.5 | -4.8 | 5.6 | 5.4 | 1.7 | -5.0 | 15.4 | -15.2 | -2.3 | 8.5 | 6.6 |
| 14611 | 20000102 | 1 | 3.6 | -1.2 | -3.6 | 7.3 | 6.5 | -0.3 | 7.9 | 2.3 | -0.9 | 6.2 | 5.0 | 1.9 | -0.8 | 4.2 | -13.7 | 1.3 | 7.9 | 9.6 |
| 14612 | 20000103 | 1 | 2.2 | -1.0 | -0.8 | 8.4 | 7.7 | 3.2 | 9.4 | 3.5 | -0.3 | 6.8 | 3.5 | -0.4 | 1.2 | 3.8 | -9.2 | 0.8 | 8.1 | 8.6 |
| 14613 | 20000104 | 1 | 3.9 | -1.3 | -1.0 | 6.4 | 7.8 | 3.7 | 7.0 | 4.8 | -3.6 | 7.3 | 4.3 | 3.8 | 2.1 | 6.0 | -5.6 | 3.5 | 8.6 | 8.1 |
| 14614 | 20000105 | 1 | 6.0 | -0.8 | 0.2 | 4.4 | 5.2 | 1.9 | 6.4 | 2.3 | -3.0 | 5.2 | 0.6 | 5.3 | -0.7 | 5.0 | -7.6 | -0.6 | 8.0 | 7.7 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 14971 | 20001227 | 12 | 5.2 | 12.3 | 4.4 | -1.0 | 1.4 | -1.7 | 2.2 | 1.4 | 6.4 | -0.1 | 6.8 | 0.8 | -3.2 | 13.1 | -10.3 | -0.3 | 6.7 | 1.4 |
| 14972 | 20001228 | 12 | 2.6 | 11.7 | 6.2 | 0.5 | 1.1 | -0.7 | -0.3 | 1.0 | 6.4 | 0.8 | 5.4 | 1.6 | -3.5 | 11.3 | -10.4 | 0.7 | 2.4 | 2.0 |
| 14973 | 20001229 | 12 | 1.1 | 7.4 | 4.6 | 0.6 | 0.3 | -1.1 | -2.2 | -1.5 | 3.0 | 0.2 | 8.6 | -0.7 | -4.3 | 10.5 | -10.5 | 0.3 | 3.3 | 2.4 |
| 14974 | 20001230 | 12 | 1.0 | 4.3 | 2.5 | 1.7 | 1.3 | -3.0 | -1.1 | 0.2 | 1.6 | 0.6 | 7.0 | -0.4 | -7.3 | 7.5 | -13.9 | 1.2 | 1.2 | 3.7 |
| 14975 | 20001231 | 12 | 0.6 | 2.0 | 1.3 | -0.1 | 1.2 | 1.0 | 2.8 | -0.8 | -0.5 | 1.2 | 4.8 | -2.7 | -13.3 | 9.5 | -16.7 | -0.8 | 1.9 | 4.8 |
366 rows × 20 columns
In [12]:
#02.6 Describe dataframe
dfyear.describe()
Out[12]:
| DATE | MONTH | BASEL_temp_mean | BELGRADE_temp_mean | BUDAPEST_temp_mean | DEBILT_temp_mean | DUSSELDORF_temp_mean | GDANSK_temp_mean | HEATHROW_temp_mean | KASSEL_temp_mean | LJUBLJANA_temp_mean | MAASTRICHT_temp_mean | MADRID_temp_mean | MUNCHENB_temp_mean | OSLO_temp_mean | ROMA_temp_mean | SONNBLICK_temp_mean | STOCKHOLM_temp_mean | TOURS_temp_mean | VALENTIA_temp_mean | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 3.660000e+02 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 | 366.000000 |
| mean | 2.000067e+07 | 6.513661 | 11.786612 | 14.195902 | 12.694262 | 10.896995 | 11.449454 | 9.173497 | 11.582514 | 10.081967 | 12.181148 | 11.123497 | 15.006557 | 10.592896 | 7.801639 | 16.014754 | -4.286885 | 8.497814 | 12.313115 | 10.758197 |
| std | 3.457653e+02 | 3.455958 | 6.455730 | 8.963638 | 8.408440 | 5.450340 | 5.852145 | 6.340916 | 5.155321 | 6.358591 | 7.858359 | 5.788827 | 7.130383 | 7.224441 | 6.646408 | 6.372385 | 6.422520 | 6.546361 | 5.611616 | 3.722074 |
| min | 2.000010e+07 | 1.000000 | -6.800000 | -9.900000 | -6.600000 | -2.800000 | -2.600000 | -10.400000 | -2.200000 | -6.500000 | -7.900000 | -3.400000 | 0.600000 | -12.200000 | -13.300000 | 1.700000 | -23.500000 | -10.100000 | -2.000000 | 1.400000 |
| 25% | 2.000040e+07 | 4.000000 | 6.825000 | 7.400000 | 5.950000 | 6.600000 | 6.925000 | 4.400000 | 7.600000 | 5.400000 | 6.325000 | 6.800000 | 9.400000 | 5.225000 | 2.900000 | 10.400000 | -8.750000 | 3.025000 | 8.200000 | 7.900000 |
| 50% | 2.000070e+07 | 7.000000 | 11.800000 | 15.300000 | 13.750000 | 10.800000 | 11.450000 | 9.900000 | 11.400000 | 10.050000 | 13.150000 | 11.050000 | 13.900000 | 10.800000 | 8.550000 | 16.050000 | -3.700000 | 9.300000 | 11.600000 | 10.500000 |
| 75% | 2.000098e+07 | 9.750000 | 17.100000 | 20.700000 | 19.300000 | 15.200000 | 15.775000 | 14.475000 | 15.875000 | 15.375000 | 18.300000 | 15.675000 | 21.400000 | 16.375000 | 13.175000 | 21.400000 | 0.575000 | 13.900000 | 17.175000 | 13.900000 |
| max | 2.000123e+07 | 12.000000 | 25.100000 | 32.800000 | 29.500000 | 25.900000 | 28.600000 | 22.200000 | 25.400000 | 25.400000 | 26.900000 | 26.900000 | 29.400000 | 26.800000 | 19.900000 | 29.500000 | 8.500000 | 21.700000 | 26.200000 | 19.500000 |
03 Visualization for one weather station¶
In [14]:
#03.1 Drop date and month
notempyear = dfyear.drop(['DATE','MONTH'], axis=1)
In [15]:
#03.2 Plot all weather data for all stations for a year
#X = weather station
#Y = day of the year
#Z = temperature
fig = go.Figure(data=[go.Surface(z=notempyear.values)])
fig.update_layout(title='Temperatures over time', autosize=False,
width=600, height=600)
fig.show()
In [16]:
#We need to make an index for the year. Create a set of data from 1 to 365 (or to 366 if it's a leap year!)
#We'll scale this by 100 as the index is made. This will help the gradient descent converge 366 = 3.66
i = np.arange(0.01,3.67,0.01)
index = pd.DataFrame(data = i, columns = ['index'])
index
Out[16]:
| index | |
|---|---|
| 0 | 0.01 |
| 1 | 0.02 |
| 2 | 0.03 |
| 3 | 0.04 |
| 4 | 0.05 |
| ... | ... |
| 361 | 3.62 |
| 362 | 3.63 |
| 363 | 3.64 |
| 364 | 3.65 |
| 365 | 3.66 |
366 rows × 1 columns
In [17]:
#03.4 Count of rows
n_rows = dfyear.shape[0]
n_rows
Out[17]:
366
In [18]:
#This will translate your chosen weather data into the X and y datasets needed for the optimization function.
X=index.to_numpy().reshape(n_rows,1)
#Represent x_0 as a vector of 1s for vector computation
ones = np.ones((n_rows,1))
X = np.concatenate((ones, X), axis=1)
y=dfyear['MADRID_temp_mean'].to_numpy().reshape(n_rows,1) #<----INSERT WEATHER STATION HERE"
In [19]:
#03.6 show shape of data
X.shape, y.shape
Out[19]:
((366, 2), (366, 1))
In [20]:
#03.7 One year of temperature data from 2000 Heathrow
plt.scatter(x=index['index'], y=dfyear['MADRID_temp_mean'])
plt.xlabel('X'); plt.ylabel('y');
plt.title('Input dataset');
In [21]:
#03.8 Find min temp
dfyear['MADRID_temp_mean'].min()
Out[21]:
0.6
In [22]:
#03.9 Find max temp
dfyear['MADRID_temp_mean'].max()
Out[22]:
29.4
04 Gradient Descent¶
In [24]:
#04.1 Compute loss function This computes the loss function for the gradiant descent. DO NOT CHANGE!
def compute_cost(X, y, theta=np.array([[0],[0]])):
"""Given covariate matrix X, the prediction results y and coefficients theta
compute the loss"""
m = len(y)
J=0 # initialize loss to zero
# reshape theta
theta=theta.reshape(2,1)
# calculate the hypothesis - y_hat
h_x = np.dot(X,theta)
#print(h_x)
# subtract y from y_hat, square and sum
error_term = sum((h_x - y)**2)
# divide by twice the number of samples - standard practice.
loss = error_term/(2*m)
return loss
In [25]:
#04.2 compute cost
compute_cost(X,y)
Out[25]:
array([137.95010929])
In [26]:
#04.3 Gradiant Descent Function
def gradient_descent(X, y, theta=np.array([[0],[0]]),
alpha=0.01, num_iterations=1500):
"""Solve for theta using Gradient Descent optimiztion technique. Alpha is the learning rate"""
m = len(y)
J_history = []
theta0_history = []
theta1_history = []
theta = theta.reshape(2,1)
for i in range(num_iterations):
error = (np.dot(X, theta) - y)
term0 = (alpha/m) * sum(error* X[:,0].reshape(m,1))
term1 = (alpha/m) * sum(error* X[:,1].reshape(m,1))
# update theta
term_vector = np.array([[term0],[term1]])
#print(term_vector)
theta = theta - term_vector.reshape(2,1)
# store history values
theta0_history.append(theta[0].tolist()[0])
theta1_history.append(theta[1].tolist()[0])
J_history.append(compute_cost(X,y,theta).tolist()[0])
return (theta, J_history, theta0_history, theta1_history)
In [27]:
#04.4 Run data through gradient descent
num_iterations=250 #<---Decide how many iterations you need. Start small and work up. Over 10,000 iterations will take a few seconds.
theta_init=np.array([[0],[0]]) #<---this is where you put the guess for [theta0], [theta1]. Start with 1 and 1.
alpha=0.1 #<---Decide what your step size is. Try values between 0.1 and 0.00001. You will need to adjust your iterations.
#If your solution is not converging, try a smaller step size.
theta, J_history, theta0_history, theta1_history = gradient_descent(X,y, theta_init,
alpha, num_iterations)
In [28]:
#04.5 show theta
theta
Out[28]:
array([[12.80532739],
[ 1.19387058]])
In [29]:
#04.6 Plot loss, theta0 and theta1. Loss should trend toward 0.
fig, ax1 = plt.subplots()
# plot thetas over time
color='tab:blue'
ax1.plot(theta0_history, label='theta_{0}', linestyle='--', color=color)
ax1.plot(theta1_history, label='theta_{1}', linestyle='-', color=color)
# ax1.legend()
ax1.set_xlabel('Iterations'); ax1.set_ylabel('theta', color=color);
ax1.tick_params(axis='y', labelcolor=color)
# plot loss function over time
color='tab:red'
ax2 = ax1.twinx()
ax2.plot(J_history, label='Loss function', color=color)
ax2.set_title('Values of theta and J(theta) over iterations')
ax2.set_ylabel('Loss: J(theta)', color=color)
ax1.tick_params(axis='y', labelcolor=color)
# ax2.legend();
fig.legend();
plt.show()
In [30]:
%%time
# theta range
theta0_vals = np.linspace(-10,10,100) #Look in the chart above for the limits of where theta0 and theta1 appear.
theta1_vals = np.linspace(-10,10,100) #Put those values as the first two \"linspace\" numbers in these lines
#Select with large margins, maybe +/- 10
J_vals = np.zeros((len(theta0_vals), len(theta1_vals)))
# compute cost for each combination of theta
c1=0; c2=0
for i in theta0_vals:
for j in theta1_vals:
t = np.array([i, j])
J_vals[c1][c2] = compute_cost(X, y, t.transpose()).tolist()[0]
c2=c2+1
c1=c1+1
c2=0 # reinitialize to 0"
CPU times: total: 2.22 s Wall time: 2.21 s
In [31]:
#This figure shows the loss function.
#X = Theta0
#Y - Theta1
#Z = Loss
#Find where it is closest to 0 in X and Y!
#you can click/hold in the graph below to rotate!
fig = go.Figure(data=[go.Surface(x=theta1_vals, y=theta0_vals, z=J_vals)])
fig.update_layout(title='Loss function for different thetas', autosize=True,
width=600, height=600, xaxis_title='theta0',
yaxis_title='theta1')
fig.show()
In [32]:
#Here is the same figure as above, with the line the loss function takes toward the minimum.
#X = Theta0
#Y - Theta1
#Z = Loss
#black line = path of loss function over the iterations.
#Find where it is closest to 0 in X and Y!
#you can click/hold in the graph below to rotate!
line_marker = dict(color='#101010', width=2)
fig = go.Figure()
fig.add_surface(x=theta1_vals, y=theta0_vals, z=J_vals)
fig.add_scatter3d(x=theta1_history, y=theta0_history, z=J_history, line=line_marker, name='')
#The below line adds a graph of just the loss over iterations in a 2D plane
plt.plot(theta0_history, theta1_history, 'r+');
fig.update_layout(title='Loss function for different thetas', autosize=True,
width=600, height=600, xaxis_title='theta0',
yaxis_title='theta1')
fig.show()
In [33]:
#Rerun the optimization above, but this time start closer to the objective!
#Find where the black line ends near the lowest X/Y/Z coordinate and make that your guess below.
num_iterations=10 #<---start with the same iterations as above
theta_init=np.array([[10],[10]]) #<---make a guess as to a more accurate [x],[y] coordinates near the minimum in the graph above.
alpha= 0.1 #<---start with the same step size as above
theta1, J_history1, theta0_history1, theta1_history1 = gradient_descent(X,y, theta_init,
alpha, num_iterations)
In [34]:
#Let's look at the new loss path on the function. It should start much closer to the goal
line_marker = dict(color='#101010', width=2)
fig = go.Figure()
fig.add_surface(x=theta1_vals, y=theta0_vals, z=J_vals)
fig.add_scatter3d(x=theta1_history1, y=theta0_history1, z=J_history1, line=line_marker, name='')
#The below line adds a graph of just the loss over iterations in a 2D plane
plt.plot(theta0_history1, theta1_history1, 'r+');
fig.update_layout(title='Loss function for different thetas', autosize=True,
width=600, height=600, xaxis_title='theta0',
yaxis_title='theta1')
fig.show()
In [35]:
#This plot shows the convergence similar to above, but only in the X/Y plane (there's no height)
plt.contour(theta0_vals, theta1_vals, J_vals, levels = np.logspace(0,10,1000))
plt.xlabel('$\\\\theta_{0}$'); plt.ylabel('$\\\\theta_{1}$')
plt.title('Contour plot of loss function for different values of $\\\\theta$s');
plt.plot(theta0_history1, theta1_history1, 'r+');
plt.show()
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) File ~\anaconda3\Lib\site-packages\IPython\core\formatters.py:343, in BaseFormatter.__call__(self, obj) 341 pass 342 else: --> 343 return printer(obj) 344 # Finally look for special method names 345 method = get_real_method(obj, self.print_method) File ~\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:170, in print_figure(fig, fmt, bbox_inches, base64, **kwargs) 167 from matplotlib.backend_bases import FigureCanvasBase 168 FigureCanvasBase(fig) --> 170 fig.canvas.print_figure(bytes_io, **kw) 171 data = bytes_io.getvalue() 172 if fmt == 'svg': File ~\anaconda3\Lib\site-packages\matplotlib\backend_bases.py:2164, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs) 2161 # we do this instead of `self.figure.draw_without_rendering` 2162 # so that we can inject the orientation 2163 with getattr(renderer, "_draw_disabled", nullcontext)(): -> 2164 self.figure.draw(renderer) 2165 if bbox_inches: 2166 if bbox_inches == "tight": File ~\anaconda3\Lib\site-packages\matplotlib\artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs) 93 @wraps(draw) 94 def draw_wrapper(artist, renderer, *args, **kwargs): ---> 95 result = draw(artist, renderer, *args, **kwargs) 96 if renderer._rasterizing: 97 renderer.stop_rasterizing() File ~\anaconda3\Lib\site-packages\matplotlib\artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer) 69 if artist.get_agg_filter() is not None: 70 renderer.start_filter() ---> 72 return draw(artist, renderer) 73 finally: 74 if artist.get_agg_filter() is not None: File ~\anaconda3\Lib\site-packages\matplotlib\figure.py:3154, in Figure.draw(self, renderer) 3151 # ValueError can occur when resizing a window. 3153 self.patch.draw(renderer) -> 3154 mimage._draw_list_compositing_images( 3155 renderer, self, artists, self.suppressComposite) 3157 for sfig in self.subfigs: 3158 sfig.draw(renderer) File ~\anaconda3\Lib\site-packages\matplotlib\image.py:132, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite) 130 if not_composite or not has_images: 131 for a in artists: --> 132 a.draw(renderer) 133 else: 134 # Composite any adjacent images together 135 image_group = [] File ~\anaconda3\Lib\site-packages\matplotlib\artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer) 69 if artist.get_agg_filter() is not None: 70 renderer.start_filter() ---> 72 return draw(artist, renderer) 73 finally: 74 if artist.get_agg_filter() is not None: File ~\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:3034, in _AxesBase.draw(self, renderer) 3031 for spine in self.spines.values(): 3032 artists.remove(spine) -> 3034 self._update_title_position(renderer) 3036 if not self.axison: 3037 for _axis in self._axis_map.values(): File ~\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:2978, in _AxesBase._update_title_position(self, renderer) 2976 top = max(top, bb.ymax) 2977 if title.get_text(): -> 2978 ax.yaxis.get_tightbbox(renderer) # update offsetText 2979 if ax.yaxis.offsetText.get_text(): 2980 bb = ax.yaxis.offsetText.get_tightbbox(renderer) File ~\anaconda3\Lib\site-packages\matplotlib\axis.py:1352, in Axis.get_tightbbox(self, renderer, for_layout_only) 1350 # take care of label 1351 if self.label.get_visible(): -> 1352 bb = self.label.get_window_extent(renderer) 1353 # for constrained/tight_layout, we want to ignore the label's 1354 # width/height because the adjustments they make can't be improved. 1355 # this code collapses the relevant direction 1356 if for_layout_only: File ~\anaconda3\Lib\site-packages\matplotlib\text.py:956, in Text.get_window_extent(self, renderer, dpi) 951 raise RuntimeError( 952 "Cannot get window extent of text w/o renderer. You likely " 953 "want to call 'figure.draw_without_rendering()' first.") 955 with cbook._setattr_cm(self.figure, dpi=dpi): --> 956 bbox, info, descent = self._get_layout(self._renderer) 957 x, y = self.get_unitless_position() 958 x, y = self.get_transform().transform((x, y)) File ~\anaconda3\Lib\site-packages\matplotlib\text.py:381, in Text._get_layout(self, renderer) 379 clean_line, ismath = self._preprocess_math(line) 380 if clean_line: --> 381 w, h, d = _get_text_metrics_with_cache( 382 renderer, clean_line, self._fontproperties, 383 ismath=ismath, dpi=self.figure.dpi) 384 else: 385 w = h = d = 0 File ~\anaconda3\Lib\site-packages\matplotlib\text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi) 66 """Call ``renderer.get_text_width_height_descent``, caching the results.""" 67 # Cached based on a copy of fontprop so that later in-place mutations of 68 # the passed-in argument do not mess up the cache. ---> 69 return _get_text_metrics_with_cache_impl( 70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi) File ~\anaconda3\Lib\site-packages\matplotlib\text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi) 73 @functools.lru_cache(4096) 74 def _get_text_metrics_with_cache_impl( 75 renderer_ref, text, fontprop, ismath, dpi): 76 # dpi is unused, but participates in cache invalidation (via the renderer). ---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath) File ~\anaconda3\Lib\site-packages\matplotlib\backends\backend_agg.py:217, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath) 213 return super().get_text_width_height_descent(s, prop, ismath) 215 if ismath: 216 ox, oy, width, height, descent, font_image = \ --> 217 self.mathtext_parser.parse(s, self.dpi, prop) 218 return width, height, descent 220 font = self._prepare_font(prop) File ~\anaconda3\Lib\site-packages\matplotlib\mathtext.py:79, in MathTextParser.parse(self, s, dpi, prop, antialiased) 77 prop = prop.copy() if prop is not None else None 78 antialiased = mpl._val_or_rc(antialiased, 'text.antialiased') ---> 79 return self._parse_cached(s, dpi, prop, antialiased) File ~\anaconda3\Lib\site-packages\matplotlib\mathtext.py:100, in MathTextParser._parse_cached(self, s, dpi, prop, antialiased) 97 if self._parser is None: # Cache the parser globally. 98 self.__class__._parser = _mathtext.Parser() --> 100 box = self._parser.parse(s, fontset, fontsize, dpi) 101 output = _mathtext.ship(box) 102 if self._output_type == "vector": File ~\anaconda3\Lib\site-packages\matplotlib\_mathtext.py:2165, in Parser.parse(self, s, fonts_object, fontsize, dpi) 2162 result = self._expression.parseString(s) 2163 except ParseBaseException as err: 2164 # explain becomes a plain method on pyparsing 3 (err.explain(0)). -> 2165 raise ValueError("\n" + ParseException.explain(err, 0)) from None 2166 self._state_stack = [] 2167 self._in_subscript_or_superscript = False ValueError: $\\theta_{1}$ ^ ParseException: Expected end of text, found '$' (at char 0), (line:1, col:1)
<Figure size 640x480 with 1 Axes>
In [ ]: